package cn.xenosp.server.common.filter;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.xenosp.server.common.Constant;
import cn.xenosp.server.common.Result;
import cn.xenosp.server.common.SystemConfig;
import cn.xenosp.server.common.cache.Cache;
import cn.xenosp.server.common.tools.IdUtil;
import cn.xenosp.server.common.tools.PropertiesUtil;
import cn.xenosp.server.module.user.entity.SysUser;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 项目名： service-web
 * 包路径： cn.xenosp.server.common.filear
 * 作者：   TongHui
 * 创建时间: 2024-08-25 10:22
 * 描述: 请求校验过滤器
 * 版本: 1.0
 */
@Slf4j
@Data
public class RequestVerifyFilter implements Filter {

    Cache redisCache;

    String baseUrl = null;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (baseUrl == null){
            SystemConfig systemConfig = (SystemConfig) redisCache.get(Constant.SYSTEM_CONFIG);
            baseUrl = systemConfig.getBasePath() + systemConfig.getApiBaseUrl();
        }

        String url ="";
        if (!(servletRequest instanceof HttpServletRequest) && !(servletResponse instanceof  HttpServletResponse)) {
            filterChain.doFilter(servletRequest, servletResponse);
        }else {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            url = request.getRequestURI();
            if (blacklisting(url)){
                // 白名单
                filterChain.doFilter(servletRequest, servletResponse);
            }else {
                try {
                    StpUtil.checkActiveTimeout();
                } catch (NotLoginException e) {
                    e.printStackTrace();
                    log.warn("token已冻结，进行续签");
                    StpUtil.updateLastActiveToNow();
                }
                String tokenValue = StpUtil.getTokenValue();
                String token = request.getHeader("Access-Token");
                if (StrUtil.isEmpty(token)
                        || StpUtil.getLoginIdByToken(token)==null || !tokenValue.equals(token)){
                    response.setContentType("application/json");
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    PrintWriter writer = response.getWriter();
                    writer.write(JSONUtil.toJsonStr(new Result(Constant.TOKEN_NULL,"非法访问")));
                    writer.flush();
                    writer.close();
                }else {
                    /*long tokenTimeout = StpUtil.getTokenTimeout();
                    if (tokenTimeout > 0 && tokenTimeout < 300){
                        // 距离过期时间不到 5分钟时进行续签
                        Map<String,Object> map = (Map<String, Object>) redisCache.get(Constant.TOKEN+"_"+token);
                        SysUser user = (SysUser) map.get("user");
                        boolean remember = (boolean) map.get("remember");

                        StpUtil.login(user.getId(),remember);
                        redisCache.expire(Constant.TOKEN + "_" + token, SaManager.getConfig().getTimeout());
                    }*/
                    filterChain.doFilter(servletRequest, servletResponse);
                }
            }
        }


    }


    private boolean blacklisting(String url){
        String regex = "^/[^/]+/$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(url);
        if (matcher.find() || url.equals(baseUrl)){
            //根路径
            return true;
        }

        // 白名单排除路径
        String excludedUrl = PropertiesUtil.get("blacklisting.excludedUrl");
        if (!excludedUrl.isEmpty()){
            String[] excludedUrlSplit = excludedUrl.split(",");
            for (String path : excludedUrlSplit) {
                if (path.endsWith("/*")){
                    path = path.substring(0,path.length()-1);
                }
                if (url.contains(path)) {
                    return false;
                }
            }
        }


        // 白名单路径
        String urlPatterns = PropertiesUtil.get("blacklisting.urlPatterns");
        String[] split = urlPatterns.split(",");
        for (String path : split) {
            if (path.startsWith("*.") && url.endsWith(path.substring(1))){
              return true;
            }else if (path.endsWith("/*")){
                path = path.substring(0,path.length()-1);
            }
            if (url.contains(path)){
                return true;
            }
        }
        return false;
    }
}
